package com.member.mp.web;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.member.common.core.domain.R;
import com.member.common.core.page.PageResult;
import com.member.common.core.page.TableDataInfo;
import com.member.common.enums.OrderDeleteEnum;
import com.member.common.utils.DateUtils;
import com.member.common.utils.StringUtils;
import com.member.common.utils.bean.BeanUtils;
import com.member.mp.aop.DistributeLock;
import com.member.mp.web.user.SupperController;
import com.member.shop.domain.*;
import com.member.shop.dto.OrderGoodsDto;
import com.member.shop.dto.OrderPerDto;
import com.member.shop.service.*;
import com.member.shop.vo.*;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 【订单】控制器
 *
 * @author wangxin
 * @version 1.0
 * @date Mon Jul 03 22:06:51 CST 2024
 **/
@Slf4j
@RestController
@RequestMapping("/wx/order")
@Api(value = "订单接口", tags = {"订单接口"})
public class OrderController extends SupperController {

    @Resource
    private ISysBizOrderService sysBizOrderService;
    public static final String CART_KEY = "CART:";
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private ISysBizUserService sysBizUserService;
    @Resource
    private ISysBizUserAddressService userAddressService;
    @Resource
    private ISysBizOrderGoodsService sysBizOrderGoodsService;
    @Resource
    private ISysBizTenantService sysBizTenantService;
    @Resource
    public RedisTemplate redisTemplate;
    @Resource
    private ISysBizGoodsService goodsService;

    /**
     * 查询订单列表
     *
     * @param status 订单状态 待支付：10、已支付：15、待发货：20、已发货：30、已完成：40、已取消：90、售后中: 80、售后成功：85、售后失败：88、全部:100
     * @return 结果
     */
    @GetMapping("/queryOrderByUser/{status}")
    public R<PageResult<OrderVo>> queryOrderByUser(@PathVariable Integer status) {
        SysBizUser loginUser = getLoginUser();
        Long userId = loginUser.getId();
        Long tenantId = loginUser.getTenantId();
        startPage();

        List<OrderVo> orderVoList = new ArrayList<>();
        LambdaQueryWrapper<SysBizOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysBizOrder::getUserId, userId);
        wrapper.eq(SysBizOrder::getTenantId, tenantId);
        wrapper.eq(status != 100, SysBizOrder::getStatus, status);
        wrapper.eq(SysBizOrder::getDelStatus, OrderDeleteEnum.NOT_DELETE.getKey());
        wrapper.orderByDesc(status == 90, SysBizOrder::getCancelTime);
        wrapper.orderByDesc(status != 90, SysBizOrder::getId);
        List<SysBizOrder> sysBizOrders = sysBizOrderService.selectSysBizOrderList(wrapper);

        if (CollectionUtils.isEmpty(sysBizOrders)) {
            return R.ok();
        }
        for (SysBizOrder sysBizOrder : sysBizOrders) {
            OrderVo orderVo = new OrderVo();
            BeanUtils.copyProperties(sysBizOrder, orderVo);
            List<OrderGoodsVo> orderGoodsVoList = new ArrayList<>();
            List<SysBizOrderGoods> sysBizOrderGoodsList = sysBizOrderGoodsService.selectSysBizOrderGoodsList(new LambdaQueryWrapper<SysBizOrderGoods>().eq(SysBizOrderGoods::getOrderId, sysBizOrder.getId()));
            for (SysBizOrderGoods sysBizOrderGoods : sysBizOrderGoodsList) {
                orderGoodsVoList.add(OrderGoodsVo.builder().id(sysBizOrderGoods.getGoodsId()).goodsName(sysBizOrderGoods.getGoodsName()).cover(sysBizOrderGoods.getSkuPic()).skuId(sysBizOrderGoods.getSkuId()).number(sysBizOrderGoods.getNumber()).marketPrice(sysBizOrderGoods.getMarketPrice() == null ? sysBizOrderGoods.getUnitPrice() : sysBizOrderGoods.getMarketPrice()).salesPrice(sysBizOrderGoods.getUnitPrice()).specsKey(sysBizOrderGoods.getSpecsKey()).build());
            }
            orderVo.setOrderGoodsVoList(orderGoodsVoList);
            orderVoList.add(orderVo);
        }

        if (CollectionUtils.isEmpty(orderVoList)) {
            return R.ok();
        }
        TableDataInfo dataTable2 = getDataTable(sysBizOrders);
        return R.ok(new PageResult<>(dataTable2.getTotal(), orderVoList));
    }


    /**
     * 查询截单时间
     * @return 结果
     */
    @GetMapping("/submitPre")
    public R<LimitOrderVo> submitPre() {
        SysBizUser loginUser = getLoginUser();
        Long tenantId = loginUser.getTenantId();

        LimitOrderVo orderDataVo = new LimitOrderVo();
        SysBizTenant bizTenant = sysBizTenantService.getById(tenantId);
        log.info("--------------- 查询截单时间 bizTenant:{} , beginTime:{}, endTime:{}", tenantId, bizTenant.getRuleBeginTime(), bizTenant.getRuleEndTime());
        if (bizTenant != null) {
            String begin = bizTenant.getRuleBeginTime(); // 22:00
            String end = bizTenant.getRuleEndTime();     // 05:00
            LocalTime currentTime = LocalTime.now();

            LocalTime startTime = LocalTime.parse(begin, DateTimeFormatter.ofPattern("HH:mm"));
            LocalTime endTime = LocalTime.parse(end, DateTimeFormatter.ofPattern("HH:mm"));
            boolean isProhibited = false;

            if (endTime.isBefore(startTime)) {
                // 跨天情况（例如 22:00 - 05:00）
                if (currentTime.isAfter(startTime) || currentTime.isBefore(endTime)) {
                    isProhibited = true;
                }
            } else {
                // 非跨天情况（例如 09:00 - 17:00）
                if (currentTime.isAfter(startTime) && currentTime.isBefore(endTime)) {
                    isProhibited = true;
                }
            }

            if (isProhibited) {
                /////// 23:00~7:00为系统处理订单时间，暂不支持下单
                log.info("{}~{}为系统处理订单时间，暂不支持下单", startTime, endTime);
                orderDataVo.setOrderLimitTime(startTime + "~" + endTime + "为系统处理订单时间，暂不支持下单");
                return R.ok(orderDataVo);
            }
        }
        return R.ok(orderDataVo);
    }


    /**
     * 准备订单数据(修改，新增优惠券列表和余额支付，之前的余额修改为分账金)
     *
     * @param orderPerDto 参数
     * @return 活动列表
     */
    @PostMapping("/pre")
    public R<OrderDataVo> pre(@RequestBody @Validated OrderPerDto orderPerDto) {
        OrderDataVo orderDataVo = new OrderDataVo();
        SysBizUser byId = sysBizUserService.getById(getUserId());
        if (byId.getUserRole() == 0) {
            return R.notRegister("请先注册会员");
        }
        try {
            // 准备订单数据, 判断是否存在异常信息
            String preorder = sysBizOrderService.preorder(orderDataVo, orderPerDto, getUserId());
            if (StringUtils.isNotEmpty(preorder)) {
                return R.fail(preorder);
            }
            return R.ok(orderDataVo);
        } catch (Exception e) {
            log.error("准备订单数据异常, error => ", e);
            return R.fail("准备订单数据异常");
        }
    }

    /**
     * 预订单(修改，新增优惠券列表和余额支付，之前的余额修改为分账金)
     *
     * @param orderPerDto 参数
     * @return 活动列表
     */
    @DistributeLock(prefix = "ORDER", cacheKey = "ORDER:LOCK:", appendUserId = true, lockTime = 10)
    @PostMapping("/preorder")
    public R<SysBizOrder> preorder(@RequestBody @Validated OrderPerDto orderPerDto) throws WxErrorException {
        SysBizOrder sysBizOrder = new SysBizOrder();
        PayVo payVo = new PayVo();

        try {

            SysBizUser loginUser = getLoginUser();
            Long userId = loginUser.getId();
            Long tenantId = loginUser.getTenantId();
            String preorder = sysBizOrderService.preorderNew(sysBizOrder, orderPerDto, userId, tenantId, payVo);
            if (StringUtils.isNotEmpty(preorder)) {
                return R.fail(preorder);
            }
            if ("1".equals(orderPerDto.getOrderType())) {
                String key = CART_KEY + tenantId + ":" + userId;
                BoundHashOperations<String, Object, Object> cartMap = stringRedisTemplate.boundHashOps(key);
                for (OrderGoodsDto orderGoodsDto : orderPerDto.getOrderGoodsDtoList()) {

                    String goodsKey = orderGoodsDto.getGoodsId() + "_" + orderGoodsDto.getSpecsKey();
                    cartMap.delete(goodsKey);
                    log.info(userId + ",删除购物车商品：" + goodsKey);
                }
            }
            return R.ok(sysBizOrder);
        } catch (Exception e) {
            log.error("预定单操作, error => ", e);
            return R.fail("预定单操作异常");
        }
    }

    /**
     * 纯余额支付
     *
     * @param id 订单id
     * @return
     */
    @PostMapping("/balanceDiscount/{id}")
    public R<String> balanceDiscount(@PathVariable Long id) {
        SysBizOrder sysBizOrder = sysBizOrderService.selectSysBizOrderById(id);
        if (sysBizOrder == null) {
            return R.fail("订单不存在");
        }

        List<SysBizOrderGoods> list = sysBizOrderGoodsService.list(new LambdaQueryWrapper<SysBizOrderGoods>()
                .eq(SysBizOrderGoods::getOrderId, sysBizOrder.getId()));

        List<Long> ids = list.stream().map(SysBizOrderGoods::getGoodsId).distinct().collect(Collectors.toList());

        List<SysBizGoods> goodsList = goodsService.list(new LambdaQueryWrapper<SysBizGoods>().in(SysBizGoods::getId, ids));
        if (!CollectionUtils.isEmpty(goodsList)) {
            // 获取下架商品名称列表
            List<String> offShelfNames = goodsList.stream()
                    .filter(g -> g.getGrounding() == 1)
                    .map(SysBizGoods::getName)
                    .collect(Collectors.toList());

            if (!offShelfNames.isEmpty()) {
                return R.fail("存在已下架的商品：" + String.join("，", offShelfNames) + "，请重新调整商品");
            }
        }

        Integer status = sysBizOrder.getStatus();
        if (status > 10) {
            return R.fail("订单不属于待付款状态");
        }
        if (sysBizOrder.getPaymentTimeEnd() != null && sysBizOrder.getPaymentTimeEnd().compareTo(DateUtils.getNowDate()) < 0) {
            return R.fail("订单超过付款时间即将关闭");
        }
        if (sysBizOrder.getSurplusAmount().compareTo(BigDecimal.ZERO) > 0) {
            return R.fail("订单不属于纯余额支付");
        }
        sysBizOrderService.balanceDiscount(sysBizOrder);
        return R.ok();
    }

    /**
     * 微信支付（微信支付或组合支付）
     *
     * @param id 订单id
     * @return
     */
    @PostMapping("/wxPay/{id}")
    public R<WxPayMpOrderResult> wxPay(@PathVariable Long id) throws WxPayException {
        SysBizOrder sysBizOrder = sysBizOrderService.selectSysBizOrderById(id);
        if (sysBizOrder == null) {
            return R.fail("订单不存在");
        }
        Integer status = sysBizOrder.getStatus();
        if (status > 10) {
            return R.fail("订单不属于待付款状态");
        }
        if (sysBizOrder.getPaymentTimeEnd() != null && sysBizOrder.getPaymentTimeEnd().compareTo(DateUtils.getNowDate()) < 0) {
            return R.fail("订单超过付款时间即将关闭");
        }
        if (sysBizOrder.getFuyouDiscountAmount().compareTo(BigDecimal.ZERO) <= 0) {
            return R.fail("订单属于纯余额支付");
        }
        return R.ok();//sysBizOrderService.wxPay(sysBizOrder)
    }

    /**
     * 取消订单
     *
     * @param id 订单id
     * @return 结果
     */
    @PostMapping("/cancel/{id}")
    public R<String> cancel(@PathVariable Long id) {
        String lockKey = "order_lock_push";
        try {
            Boolean lockAcquired = redisTemplate.opsForValue().setIfAbsent(lockKey, "locked", 10, TimeUnit.SECONDS); // 设置 10 秒超时锁
            if (Boolean.FALSE.equals(lockAcquired)) {
                return R.fail("订单已经被推送,稍后再试");
            }
            SysBizOrder sysBizOrder = sysBizOrderService.selectSysBizOrderById(id);
            if (sysBizOrder == null) {
                return R.fail("订单不存在");
            }
            //防止定时任务把数据改为20 所以把这个地方改成大于30
            if (sysBizOrder.getStatus() > 15) {
                log.info("---------------------------orderId:{} ---  sysBizOrder.status:{}", sysBizOrder.getId(), sysBizOrder.getStatus());
                return R.fail("订单暂不支持取消,请联系管理员");
            }
            //订单已超下单时间一小时
            if(sysBizOrder.getPaymentTime() != null){
                long currentTime = System.currentTimeMillis();
                long paymentTime = sysBizOrder.getPaymentTime().getTime();
                long oneHourInMillis = 3600000;

                if (currentTime - paymentTime > oneHourInMillis) {
                    log.info("---------------------------订单暂不支持取消,请联系管理员 ---  超过了一小时");
                    return R.fail("订单暂不支持取消,请联系管理员");
                }

            }
            // 取消订单
            sysBizOrderService.cancelOrder(sysBizOrder);
            return R.ok();
        } catch (Exception e) {
            log.error("手动取消订单异常, error => ", e);
            return R.fail("取消订单异常");
        } finally {
            redisTemplate.delete(lockKey);
        }
    }

    /**
     * 超时取消订单
     *
     * @param id 订单id
     * @return
     */
    @PostMapping("/close/{id}")
    public R<String> close(@PathVariable Long id) {
        try {
            SysBizOrder sysBizOrder = sysBizOrderService.selectSysBizOrderById(id);
            if (sysBizOrder == null) {
                return R.fail("订单不存在");
            }
            if (sysBizOrder.getStatus() > 15) {
                return R.fail("待付款或已支付订单才能取消");
            }
            log.info("支付超时 ==> 订单号: {}", sysBizOrder.getOrderCode());
            Date nowDate = DateUtils.getNowDate();
            sysBizOrder.setCancelTime(nowDate);
            sysBizOrder.setCancelReason("支付超时");
            sysBizOrder.setUpdateTime(nowDate);
            sysBizOrder.setStatus(90);
            // 关闭订单
            sysBizOrderService.cancelOrder(sysBizOrder);
            return R.ok();
        } catch (Exception e) {
            log.error("自动关闭订单异常, error => ", e);
            return R.fail("自动关闭订单异常");
        }
    }

    /**
     * 删除订单
     *
     * @param id 订单id
     * @return
     */
    @PostMapping("/deleteOrder/{id}")
    public R<String> deleteOrder(@PathVariable Long id) {
        SysBizOrder sysBizOrder = sysBizOrderService.selectSysBizOrderById(id);
        if (sysBizOrder == null) {
            return R.fail("订单不存在");
        }
        sysBizOrder.setDelStatus(OrderDeleteEnum.DELETE.getKey());
        sysBizOrder.setUpdateTime(DateUtils.getNowDate());
        sysBizOrder.setUpdateBy(getUsername());
        sysBizOrderService.updateById(sysBizOrder);
        return R.ok();
    }

    /**
     * 查询订单详情
     *
     * @param id 订单id
     * @return
     */
    @GetMapping("/queryOrderDetail/{id}")
    public R<OrderDetailVo> queryOrderDetail(@PathVariable Long id) {
        SysBizOrder sysBizOrder = sysBizOrderService.selectSysBizOrderById(id);
        if (sysBizOrder == null) {
            return R.fail("订单不存在");
        }
        OrderDetailVo orderDetailVo = sysBizOrderService.queryOrderDetail(sysBizOrder);
        return R.ok(orderDetailVo);
    }

    /**
     * 查询订单物流信息
     *
     * @param id 订单id
     * @return
     */
    @GetMapping("/queryExpressById/{id}")
    public R<ExpressVo> queryExpressById(@PathVariable Long id) {
        SysBizOrder sysBizOrder = sysBizOrderService.selectSysBizOrderById(id);
        if (sysBizOrder == null) {
            return R.fail("订单不存在");
        }
        ExpressVo expressVo = new ExpressVo();
        BeanUtils.copyProperties(sysBizOrder, expressVo);
        return R.ok(expressVo);
    }

    /**
     * 确认收货
     *
     * @param id 订单id
     * @return
     */
    @PostMapping("/confirmOrder/{id}")
    public R<String> confirmOrder(@PathVariable Long id) {
        SysBizOrder sysBizOrder = sysBizOrderService.selectSysBizOrderById(id);
        if (sysBizOrder == null) {
            return R.fail("未找到订单");
        }
        if (sysBizOrder.getStatus() != 30) {
            return R.fail("订单不是已发货状态");
        }
        sysBizOrder.setStatus(40);
        sysBizOrder.setReceiverGoodsTime(DateUtils.getNowDate());
        sysBizOrderService.updateById(sysBizOrder);
        return R.ok();
    }

    /**
     * 修改收货地址
     *
     * @param order 订单id,地址id
     * @return
     */
    @PostMapping("/updateAddress")
    public R<String> updateAddress(@RequestBody SysBizOrder order) {
        if (order.getId() == null) {
            return R.fail("订单参数错误");
        }
        if (order.getAddressId() == null) {
            return R.fail("地址参数错误");
        }

        Long orderId = order.getId();
        SysBizOrder sysBizOrder = sysBizOrderService.selectSysBizOrderById(orderId);

        Long addressId = order.getAddressId();
        SysBizUserAddress address = userAddressService.getById(addressId);
        if (address == null) {
            return R.fail("未找到地址");
        }

        if (sysBizOrder == null) {
            return R.fail("未找到订单");
        }
        if (sysBizOrder.getStatus() > 20) {
            return R.fail("当前订单状态不支持修改收货地址");
        }

        LambdaUpdateWrapper<SysBizOrder> updateWrapper = new LambdaUpdateWrapper<>();

        updateWrapper.set(SysBizOrder::getAddressId, addressId);
        updateWrapper.set(SysBizOrder::getCity, address.getCity());
        updateWrapper.set(SysBizOrder::getArea, address.getArea());
        updateWrapper.set(SysBizOrder::getProvince, address.getProvince());
        updateWrapper.set(SysBizOrder::getReceiverAddress, address.getDetails());
        updateWrapper.set(SysBizOrder::getReceiver, address.getName());
        updateWrapper.set(SysBizOrder::getContactNumber, address.getPhone());
        updateWrapper.set(SysBizOrder::getUpdateTime, new Date());
        updateWrapper.eq(SysBizOrder::getId, orderId);

        sysBizOrderService.update(updateWrapper);
        return R.ok();
    }

}
